<?php
class upload{
	public $file_temp	= "";
	public $file_name	= "";
	public $file_size	= "";
	public $file_type	= "";
	public $max_size	= 0;
	
	private $app;
	
	public function __construct(){
		global $app;
		$this->app =& $app;
		$app->{"upload"} =& $this;
	}
	
	/**
	 * 檔案上傳
	 * 
	 * @param	string	$field	表單上傳欄位的name值
	 * @param	string	$path	目標存檔位置路徑
	 * @return	bool
	 */
	public function do_upload($field = "userfile", $path){
		if (!isset($_FILES[$field])){
			app_die("沒有檔案？");
			return FALSE;
		}
		
		// 確保路徑必須為「/」結尾
		$path = rtrim($path, '/').'/';
				
		if (!is_uploaded_file($_FILES[$field]['tmp_name'])){
			app_die("非法上傳？");
			
			$err = (!isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];

			switch ($err){
				case 1:	// UPLOAD_ERR_INI_SIZE
					app_die("檔案超過INIT大小？");
					break;
				case 2: // UPLOAD_ERR_FORM_SIZE
					app_die("檔案超過FORM大小？");
					break;
				case 3: // UPLOAD_ERR_PARTIAL
					app_die("檔案上傳不完整？");
					break;
				case 4: // UPLOAD_ERR_NO_FILE
					app_die("沒有選擇檔案？");
					break;
				case 6: // UPLOAD_ERR_NO_TMP_DIR
					app_die("Temp資料夾錯誤？");
					break;
				case 7: // UPLOAD_ERR_CANT_WRITE
					app_die("檔案無法寫入？");
					break;
				case 8: // UPLOAD_ERR_EXTENSION
					app_die("檔案格式不符？");
					break;
				default :
					app_die("無法上傳");
					break;
			}
			
			return FALSE;
		}
		
		$this->file_temp = $_FILES[$field]['tmp_name'];
		$this->file_name = $this->_prep_filename($_FILES[$field]['name']);
		$this->file_size = $_FILES[$field]['size'];
		$this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
		$this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
		
		// 檢查檔案類型
		if (!$this->is_image()){
			app_die("這不是影像圖檔！");
			return FALSE;
		}
		
		// 檢查檔案大小
		if (!$this->check_filesize()){
			app_die("檔案超過大小！");
			return FALSE;
		}
				
		// 檔名安全檢查
		$this->file_name = $this->clean_file_name($this->file_name);
		
		// 去除空白字元，將空白字元用「_」取代
		$this->file_name = preg_replace("/\s+/", "_", $this->file_name);
		
		// 以上各項檢查合格，開始移動檔案
		if (!copy($this->file_temp, $path.$this->file_name)){
			if (!move_uploaded_file($this->file_temp, $path.$this->file_name)){
				app_die("無法移動檔案？目標路徑:「".$this->file_temp." => ".$path.$this->file_name."」");
				return FALSE;
			}
		}
		return TRUE;
	}
	
	/**
	* 檢查是否為影像檔
	*
	* @return	bool
	*/
	public function is_image()
	{	
		$png_mimes  = array('image/x-png');
		$jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');
	
		if (in_array($this->file_type, $png_mimes)){
			$this->file_type = 'image/png';
		}
	
		if (in_array($this->file_type, $jpeg_mimes)){
			$this->file_type = 'image/jpeg';
		}
	
		$img_mimes = array(
			'image/gif',
			'image/jpeg',
			'image/png'
		);
	
		return (in_array($this->file_type, $img_mimes, TRUE)) ? TRUE : FALSE;
	}
	
	/**
	* 檢查檔案大小，檔案限制大小由max_size參數決定，單位是KB
	*
	* @return	bool
	*/
	public function check_filesize(){
		if ($this->max_size > 0  &&  $this->file_size > $this->max_size){
			return FALSE;
		}else{
			return TRUE;
		}
	}
	
	/**
	* 檔名安全檢查，過濾可能的非法字元
	*
	* @param	string	$filename
	* @return	string	stripslashes($filename)
	*/
	public function clean_file_name($filename)
	{
		$bad = array(
			"<!--",
			"-->",
			"'",
			"<",
			">",
			'"',
			'&',
			'$',
			'=',
			';',
			'?',
			'/',
			"%20",
			"%22",
			"%3c",		// <
			"%253c",	// <
			"%3e",		// >
			"%0e",		// >
			"%28",		// (
			"%29",		// )
			"%2528",	// (
			"%26",		// &
			"%24",		// $
			"%3f",		// ?
			"%3b",		// ;
			"%3d"		// =
		);
	
		$filename = str_replace($bad, '', $filename);
	
		return stripslashes($filename);
	}
	
	/**
	* Prep Filename
	*
	* Prevents possible script execution from Apache's handling of files multiple extensions
	* http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext
	*
	* 檔名安全檢查，本段程式碼參考自CodeIgniter2.0.2
	*
	* @param	string	$filename
	* @return	string	$filename
	*/
	protected function _prep_filename($filename)
	{
	if (strpos($filename, '.') === FALSE OR $this->allowed_types == '*')
	{
	return $filename;
	}
	
		$parts		= explode('.', $filename);
		$ext		= array_pop($parts);
		$filename	= array_shift($parts);
	
		foreach ($parts as $part)
		{
		if ( ! in_array(strtolower($part), $this->allowed_types) OR $this->mimes_types(strtolower($part)) === FALSE)
		{
		$filename .= '.'.$part.'_';
		}
			else
			{
			$filename .= '.'.$part;
	}
	}
	
	$filename .= '.'.$ext;
	
	return $filename;
	}
}
?>